#ifndef __YUECHUAN_THREAD_H__
#define __YUECHUAN_THREAD_H__

#include <thread>
#include <functional>
#include <memory>
#include <pthread.h>
#include <semaphore.h>
#include <string>
#include "mutex.h"

namespace yuechuan {

    class Thread {
    public:
        typedef std::shared_ptr<Thread> ptr;
        /**
         * @brief 自定义线程的构造函数
         * @param callback 线程要执行的回调函数
         * @param name 线程的名称
         */
        Thread(std::function<void()> callback, const std::string name="UNKNOW");

        /**
         * @brief 自定义线程的析构函数
         */
        ~Thread();

        /**
         * @brief 获取线程id
         *
         * @return pid_t: m_id
         */
        pid_t getId() const { return m_id; }

        /**
         * @brief 等待线程结束，使用pthread_join 传递的参数就是成员变量m_thread线程标识符，对于线程的返回值不需要保存，直接设置为nullptr即可
         */
        void join();

        /**
         * @brief 获取线程的名称，相对于类方法，这个可以在指定Thread中执行
         *
         * @return std::string 线程名称
         */
        std::string getName() const { return m_name; }

        /**
         * @brief 设置当前线程的名称，即线程局部变量 t_thread->m_name
         */
        static void setName(const std::string &name);


        /**
         * @brief 静态函数，方便执行函数时直接获取当前的线程
         *
         * @return Thread* 也就是局部变量thread_local Thread *t_thread.
         */
        static Thread *GetThis();

        /**
         * 静态函数，对于日志系统需要用到线程name，可直接获取
         *
         * @return std::string 局部线程名称 thread_local std::string t_thread_name
         */
        static const std::string &GetName();

        static void *run(void *arg);

    private:
        /**
         * @brief 线程不允许拷贝，引用，赋值，将这些函数定义为私有且为删除的函数
         * @brief 原因是互斥量的拷贝会破坏其作用
         */
        Thread(const Thread &) = delete;

        /**
         * @brief 线程引用也是不被允许的
         */
        Thread(const Thread &&) = delete;

        /**
         * @brief 线程总赋值不被允许
         * @return Thread&
         */
        Thread &operator=(const Thread &) = delete;

    private:
        /// 线程Id,top命令中显示的线程号
        pid_t m_id = -1;
        /// 线程 pthread_t 的类型是 unsigned long int
        pthread_t m_thread = 0;
        /// 线程回调函数
        std::function<void()> m_callback;
        /// 线程名称
        std::string m_name;
        /// 信号量
        Semaphore m_semaphore;
    };

} // namespace yuechuan

#endif
